// Copyright (c) 1996-2002 John Lyon-Smith. All rights reserved.

// Use both a preprocessor macro AND a #pragma here so that we have a #define 
// to check for header file inclusion.

#ifndef _WXTL_INCLUDED_
#define _WXTL_INCLUDED_
#endif 

#pragma once

//#ifndef _WIN32_WINNT
//// Requires to Windows 4.0 and higher
//#error _WIN32_WINNT must be 0x0400 or higher
//#endif

// Windows
#ifndef WXTL_NO_WINSOCK
#include <winsock2.h>	// I hate the way this include order works...
#endif

#include <windows.h>	

#ifndef STRICT
#error STRICT should be defined for WxTL
#endif

// CRT
#include <stdio.h>
#include <tchar.h>
#include <crtdbg.h>
#include <comdef.h>

// STL
#pragma warning(push)
#pragma warning(disable: 4100) // unreferenced formal parameter
#pragma warning(disable: 4267) // possible loss of data
#pragma warning(disable: 4275) // non-dll class used as base for dll-interface class
#pragma warning(disable: 4702) // unreachable code

#include <list>
#include <hash_map>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stdexcept>

using namespace std;
using stdext::hash_map;

// BOOST
#pragma warning(disable: 4244) // possible loss of data

//#include <boost\shared_ptr.hpp>
//#include <boost\shared_array.hpp>
//#include <boost\scoped_ptr.hpp>
//#include <boost\scoped_array.hpp>
////#include <boost\token_functions.hpp>
//#include <boost\tokenizer.hpp>

#pragma warning(pop)

#pragma warning(disable: 4290) // exception specification ignored

// This is still a useful macro to have, stolen from MFC
#ifndef VERIFY
	#ifdef _DEBUG
	#define VERIFY(f)          _ASSERTE(f)
	#else
	#define VERIFY(f)          ((void)(f))
	#endif
#endif

// Useful but not found elsewhere
#ifndef MAKEDWORD
#define MAKEDWORD(l, h)      ((DWORD)(((WORD)((DWORD_PTR)(l) & 0xffff)) | ((DWORD)((WORD)((DWORD_PTR)(h) & 0xffff))) << 16))
#endif

#define FIELDOFFSET(type, field) ((DWORD)(&((type *)0)->field))

#define WXARRAYSIZE(p) (sizeof(p)/sizeof((p)[0]))

// Alternates of the above (in case you don't like mine)
#define SIZEOF_ARRAY	ARRAYSIZE
#define DIM				ARRAYSIZE

#define STACKARRAY(T, N) (T*)_alloca(N * sizeof(T))

// Use this instead of MAX_PATH
#define WXTL_BIG_MAX_PATH	1024

// We need a tchar like Unicode/MBCS string
#ifndef _UNICODE
#define tstring string
#else
#define tstring wstring
#endif

// Macros to help with the variety of ways Windows can return errors
#define THROW_BAD_WINERROR_RET(x)	{ register DWORD dw = (x); if (dw != ERROR_SUCCESS) throw _win32_error(dw); }
#define THROW_BAD_BOOL_RET(x)		{ if (!(x)) throw _win32_error(GetLastError()); }

namespace wxtl
{
	// A template for adjusting alignment
	//
	template<class T>
	inline T align(T x, size_t b)
	{
		return T((ULONG)(x+(b-1)) & (~(b-1)));
	}

	// Define these as they are the most common forms of tokenizer class usage
	/*typedef boost::char_separator<char, std::string::traits_type> char_separator;
	typedef boost::tokenizer<wxtl::char_separator, std::string::const_iterator, std::string> tokenizer;

	typedef boost::char_separator<wchar_t, std::wstring::traits_type> wchar_separator;
	typedef boost::tokenizer<wxtl::wchar_separator, std::wstring::const_iterator, std::wstring> wtokenizer;

	typedef boost::char_separator<TCHAR, std::tstring::traits_type> tchar_separator;
	typedef boost::tokenizer<wxtl::tchar_separator, std::tstring::const_iterator, std::tstring> ttokenizer;*/

	// Stuff for COM support
	typedef HRESULT __stdcall PFN_DLLGETCLASSOBJECT(REFCLSID rclsid, REFIID riid, void **ppv);

	typedef HRESULT (* PFN_CREATEOBJECT)( REFIID riid, void **ppInterface );

	enum CO_THREADING_MODEL
	{
		modelApartment,
		modelFree,
		modelMain,
		modelBoth,
		modelNeutral	
	};

	struct CO_CLASS_REGISTER
	{	
		const CLSID *pClsid;
		CO_THREADING_MODEL model;
		PCTSTR szProgID;
		int iVersion;				
		PCTSTR szCoclassDesc;
		PFN_CREATEOBJECT pfnCreateObject;
		BOOL bSingleton;
	};

#ifdef _DEBUG
	const BOOL g_isDebugCode = true;
#else
	const BOOL g_isDebugCode = false;
#endif

#ifdef _UNICODE
	const BOOL g_isUnicode = true;
#else
	const BOOL g_isUnicode = false;
#endif

	// A simple Win32 error exception
	class _win32_error
	{
	public:
		_win32_error() throw() : m_error(ERROR_SUCCESS)
		{
		}
		_win32_error(DWORD code) throw() : m_error(code)
		{
		}
		_win32_error(const _win32_error& err)
		{
			m_error = err.m_error;
		}
		_win32_error& operator=(const _win32_error& that) throw()
		{
			this->m_error = that.m_error;
			return *this;
		}
		~_win32_error()
		{
		}
		
		DWORD error() const 
		{ 
			return m_error; 
		}

	protected:
		DWORD m_error;
	};
};

#ifndef _WXTL_NO_AUTO_NAMESPACE
using namespace wxtl;
#endif
